package cn.com.bluemoon.daps.system.controller;


import cn.com.bluemoon.daps.common.constant.DapRoleEnum;
import cn.com.bluemoon.daps.common.datascope.BmPermission;
import cn.com.bluemoon.daps.common.datascope.log.OperateLog;
import cn.com.bluemoon.daps.common.datascope.log.enums.ModuleObject;
import cn.com.bluemoon.daps.common.datascope.log.enums.OperateType;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.domain.UserInfoHolder;
import cn.com.bluemoon.daps.common.exception.DapException;
import cn.com.bluemoon.daps.common.toolkit.BmAssetUtils;
import cn.com.bluemoon.daps.domp.api.IDompService;
import cn.com.bluemoon.daps.domp.api.LocalDompService;
import cn.com.bluemoon.daps.system.entity.DapSystemBizLine;
import cn.com.bluemoon.daps.system.service.DapSystemBizLineDetailService;
import cn.com.bluemoon.daps.system.service.DapSystemBizLineService;
import cn.com.bluemoon.daps.system.service.DapSystemInfoService;
import cn.com.bluemoon.daps.system.vo.*;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 主题定义（业务线、主题、分类管理） 前端控制器
 * </p>
 *
 * @author admin
 * @since 2021-09-23
 */
@Api(tags = "业务线管理")
@RestController
@Slf4j
@RequestMapping("/topicDefine/bizLine")
@Validated
public class DapBizLineController {
    @Autowired
    private DapSystemBizLineService systemBizLineService;

    @Autowired
    private DapSystemBizLineDetailService bizLineDetailService;



    @Autowired
    private DapSystemInfoService systemInfoService;

    @GetMapping
    @ApiOperation(value = "业务线列表")
    @BmPermission(value = {"standard:topicDefine", "standard:bizLine:list"}, name = "业务线列表", ignore = false)
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = BizLineResponseVo.class, responseContainer = "List")})
    @OperateLog(type = OperateType.SELECT, moduleName = ModuleObject.SYSTEM)
    public ResultBean<List<BizLineSingleResponseVo>> bizLine(@ApiParam(value = "关键字：业务线名称、编码、全称、说明")
                                                             @RequestParam(required = false, name = "keyword") String keyword) {
        List<DapSystemBizLine> res = systemBizLineService.list(systemBizLineService.bmLambdaQuery()
                .and(StringUtils.isNotBlank(keyword),
                        w -> w.like(DapSystemBizLine::getCodeName, keyword)
                                .or().like(DapSystemBizLine::getCode, keyword)
                                .or().like(DapSystemBizLine::getFullName, keyword)
                                .or().like(DapSystemBizLine::getRemark, keyword)
                ).orderByDesc(DapSystemBizLine::getUpdateTime));
        return ResultBean.ok(res).convert(dapSystemBizLines -> dapSystemBizLines.stream()
                .map(BizLineSingleResponseVo::new).collect(Collectors.toList()));
    }

    // 业务线CRUD
    @PostMapping
    @ApiOperation(value = "业务线新增")
    @BmPermission(value = "standard:bizLine:add", name = "业务线新增", ignore = false)
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Integer.class)})
    @OperateLog(type = OperateType.INSERT, moduleName = ModuleObject.SYSTEM)
    public ResultBean<Integer> bizLineSave(@Valid @RequestBody BizLineRequestVo bizLineVo) {
        Integer bizLineId = systemBizLineService.saveOrUpdateBizLine(bizLineVo, null, UserInfoHolder.getUserInfoOrEmpty());
        return ResultBean.ok(bizLineId);
    }

    @PutMapping("/{bizLineId}")
    @ApiOperation(value = "业务线更新")
    @BmPermission(value = "standard:bizLine:edit", name = "业务线更新", ignore = false)
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Integer.class)})
    @OperateLog(type = OperateType.UPDATE, moduleName = ModuleObject.SYSTEM)
    public ResultBean<Integer> bizLineUpdate(@Valid @RequestBody BizLineRequestVo bizLineVo, @PathVariable Integer bizLineId) {
        UserInfoHolder.UserInfo userInfo = UserInfoHolder.getUserInfo().orElseThrow(() -> new DapException("获取当前用户信息失败"));
        doPermission(userInfo, bizLineVo, bizLineId);
        BmAssetUtils.notNull(bizLineId, "业务线id不可为空");
        systemBizLineService.saveOrUpdateBizLine(bizLineVo, bizLineId, UserInfoHolder.getUserInfoOrEmpty());
        return ResultBean.ok(bizLineId);
    }

    /**
     * 权限控制 1.只允许数据安全管理员或当前业务线负责人进行编辑业务线信息 2.允许数据安全、业务线负责人、业务线系统明细的数据管理员编辑系统明细
     */
    private void doPermission(UserInfoHolder.UserInfo userInfo, BizLineRequestVo newBizLine, Integer bizLineId) {
        DapRoleEnum[] roleEnums = new DapRoleEnum[]{DapRoleEnum.DATA_SECURITY_MANAGER};
        DapSystemBizLine oldBizLine = systemBizLineService.getById(bizLineId);
        BmAssetUtils.notNull(oldBizLine, "业务线已删除，请刷新");
        if (userInfo.getAccount().equalsIgnoreCase(oldBizLine.getDataManager())) {
            return;
        }

        // 普通用户 ：1.不可修改业务线基本信息
        boolean noChangeBizLineInfo = StringUtils.equals(oldBizLine.getCode(), newBizLine.getCode()) &&
                StringUtils.equals(oldBizLine.getDataManager(), newBizLine.getDataManager()) &&
                StringUtils.equals(oldBizLine.getCodeName(), newBizLine.getCodeName()) &&
                StringUtils.equals(oldBizLine.getFullName(), newBizLine.getFullName()) &&
                StringUtils.equals(oldBizLine.getRemark(), newBizLine.getRemark()) &&
                StringUtils.equals(oldBizLine.getEtlQueueName(), newBizLine.getEtlQueueName());
        BmAssetUtils.isTrue(noChangeBizLineInfo, "只允许数据安全管理员或当前业务线负责人进行编辑业务线基本信息");
        // 2. 只允许修改用户所属系统信息
        List<BizLineDetailResponseVo> oldDetails = bizLineDetailService.findBizLineDetailVos(bizLineId);
        Map<String, BizLineDetailResponseVo> oldDetailBySystemId = oldDetails.stream().collect(Collectors.toMap(BizLineDetailResponseVo::getSystemId, v -> v, (a, b) -> b));
        List<BizLineDetailRequestVo> newDetails = newBizLine.getDetails();
        for (BizLineDetailRequestVo newDetail : newDetails) {
            if (oldDetailBySystemId.containsKey(newDetail.getSystemId())) {
                BizLineDetailResponseVo oldDetail = oldDetailBySystemId.get(newDetail.getSystemId());
                // 只对有变化的进行管控
                if ((oldDetail.getAdmins().containsAll(newDetail.getAdmins()) && oldDetail.getAdmins().size() == newDetail.getAdmins().size()) &&
                        (oldDetail.getDevelops().containsAll(newDetail.getDevelops()) && oldDetail.getDevelops().size() == newDetail.getDevelops().size())) {
                    continue;
                }
                if (!oldDetail.getAdmins().contains(userInfo.getAccount())) {
                    throw new DapException("您不是系统[" + systemInfoService.getById(newDetail.getSystemId()).getName() + "]数据管理员，无权限修改");
                }
            }
        }
    }

    @DeleteMapping("/{bizLineId}")
    @ApiOperation(value = "业务线删除")
    @BmPermission(value = "standard:bizLine:delete", name = "业务线删除", ignore = false)
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @OperateLog(type = OperateType.DELETE, moduleName = ModuleObject.SYSTEM)
    public ResultBean<Boolean> bizLineDelete(@PathVariable Integer bizLineId) {
        boolean remove = systemBizLineService.deleteBizLineById(bizLineId);
        return ResultBean.ok(remove);
    }

    @GetMapping("/{bizLineId}")
    @ApiOperation(value = "业务线详情")
    @BmPermission(value = "standard:bizLine:get", name = "业务线详情", ignore = false)
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = BizLineVo.class)})
    @OperateLog(type = OperateType.SELECT, moduleName = ModuleObject.SYSTEM)
    public ResultBean<BizLineSingleResponseVo> bizLineOne(@PathVariable Integer bizLineId) {
        DapSystemBizLine bizLine = systemBizLineService.getById(bizLineId);
        return ResultBean.ok(bizLine).convert(BizLineSingleResponseVo::new);
    }

    @GetMapping("/detail")
    @ApiOperation(value = "业务线详情-系统用户信息")
    @BmPermission(value = "standard:bizLine:get", name = "业务线详情-系统用户信息", ignore = false)
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = BizLineDetailResponseVo.class, responseContainer = "List")})
    @OperateLog(type = OperateType.SELECT, moduleName = ModuleObject.SYSTEM)
    public ResultBean<List<BizLineDetailResponseVo>> bizLineDetail(@ApiParam(required = false, value = "业务线id，新增业务线可为空")
                                                                   @RequestParam(required = false) Integer bizLineId) {
        return ResultBean.ok(systemBizLineService.findBizLineDetails(bizLineId));
    }

    @GetMapping("/list")
    @ApiOperation(value = "业务线列表,提供给其他模块使用，如：模型crud")
    @BmPermission(value = "standard:bizLine:list", name = "业务线列表", ignore = true)
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = BizLineResponseVo.class, responseContainer = "List")})
    public ResultBean<List<BizLineSingleResponseVo>> bizLines() {
        return ResultBean.ok(systemBizLineService.list(systemBizLineService.bmLambdaQuery().orderByDesc(DapSystemBizLine::getUpdateTime)))
                .convert(bizLines -> bizLines.stream().map(BizLineSingleResponseVo::new).collect(Collectors.toList()));
    }
}
